/*
 * planner.h
 *
 * Copyright 2011 Pieter Agten
 *
 * This file is part of Yarf.
 *
 * Yarf is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Yarf is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Yarf.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file   planner.h
 * @author Pieter Agten (pieter.agten@gmail.com)
 * @date   23 sep 2011
 * @brief  The planner component translates movement g-code commands into 
 *         blocks that represent a linear movement and places these blocks
 *         into a queue of blocks to be executed by the block handler component.
 */

#ifndef PLANNER_H
#define PLANNER_H

#include "yarf.h"
#include "block.h"

#include <stdbool.h>

/**
 * Initializes the planner component.
 */
void plan_init(void);

/**
 * Returns the virtual position in number of steps from the origin for the
 * specified axis. The virtual position is the position the printer will be at
 * when all pending blocks in the planning queue have been executed.
 *
 * @param axis the axis for which to get the virtual position. Valid values are
 *             \a X_AXIS, \a Y_AXIS, \a Z_AXIS and \a E_AXIS.
 * @return The virtual position in number of steps for the specified axis.
 */
steps_t plan_get_virtual_position(unsigned char axis);

/**
 * Sets the virtual position of all axes. The arguments are interpreted as
 * offsets in numbers of steps relative to the current virtual position.
 *
 * @param x the number of steps to add to the virtual x position
 * @param y the number of steps to add to the virtual y position
 * @param z the number of steps to add to the virtual z position
 * @param e the number of steps to add to the virtual e position
 */
void plan_set_virtual_position_rel(steps_t x, steps_t y, steps_t z, steps_t e);

/**
 * Sets the virtual position of all axes. The arguments are interpreted as
 * absolute positions in numbers of steps from the origin.
 *
 * @param x the new virtual x position in number of steps
 * @param y the new virtual x position in number of steps
 * @param z the new virtual x position in number of steps
 * @param e the new virtual x position in number of steps
 */
void plan_set_virtual_position_abs(steps_t x, steps_t y, steps_t z, steps_t e);


/**
 * Sets a number of block parameters in order to have the block accelerate from
 * a given entry speed at the start of the block and to have it decelerate to
 * a given exit speed at the end of it. These parameters are used by the block
 * handler during execution of the block.
 *
 * @param b           a pointer to the block for which to calculate the
 *                    parameters
 * @param entry_speed the entry speed of the block in mm/min
 * @param exit_speed  the exit speed of the block in mm/min
 */
void plan_calculate_trapezoid(block_t *b, speed_t entry_speed, speed_t exit_speed);


/**
 * Adds a movement from the current virtual position to the specified position
 * at the specified feed rate to the end of the planning queue. The position
 * arguments are interpreted as offsets in numbers of steps from the current
 * virtual position.
 *
 * @param steps_x       the number of steps to take in the x direction (can be
 *                      negative), must not make the machine go out of bounds
 * @param steps_y       the number of steps to take in the y direction (can be
 *                      negative), must not make the machine go out of bounds
 * @param steps_z       the number of steps to take in the z direction (can be
 *                      negative), must not make the machine go out of bounds
 * @param steps_e       the number of steps to take in the e direction (can be
 *                      negative)
 * @param plateau_speed maximum speed of the block in mm/min
 *
 * If any of the X, Y or Z axes is not homed when calling this movement, that
 * axis is homed before making the movement.
 *
 * If any of the destination parameters would cause the machine to go out of
 * bounds, the movement is not added to the planning queue (it is silently
 * dropped).
 *
 * If the lookahead component is enabled, it is called immediately after adding
 * the new block to the queue, in order to optimize the block's entry speed and
 * to reduce the jerkiness of the transitions between blocks. The machine's
 * virtual position is updated to the position it will be in after this
 * movement has been executed.
 */
void plan_linear_movement_rel(steps_t steps_x, steps_t steps_y, steps_t steps_z, steps_t steps_e, speed_t plateau_speed);


/**
 * Adds a movement from the current virtual position to the specified position
 * at the specified feed rate to the end of the planning queue. The position
 * arguments are interpreted as absolute positions in numbers of steps from the
 * origin.
 *
 * @param dest_x        the destination position of the x axis, in steps from
 *                      the origin, must be within the bounds of the axis
 * @param dest_y        the destination position of the y axis, in steps from
 *                      the origin, must be within the bounds of the axis
 * @param dest_z        the destination position of the z axis, in steps from
 *                      the origin, must be within the bounds of the axis
 * @param dest_e        the destination position of the e axis, in steps from
 *                      the origin
 * @param plateau_speed maximum speed of the block in mm/min
 *
 * If any of the X, Y or Z axes is not homed when calling this movement, that
 * axis is homed before making the movement.
 *
 * If any of the destination parameters is out of bounds, the movement is not
 * added to the planning queue (it is silently dropped).
 *
 * If the lookahead component is enabled, it is called immediately after adding
 * the new block to the queue, in order to optimize the block's entry speed and
 * to reduce the jerkiness of the transitions between blocks. The machine's
 * virtual position is updated to the position it will be in after this
 * movement has been executed.
 */
void plan_linear_movement_abs(steps_t dest_x, steps_t dest_y, steps_t dest_z, steps_t dest_e, speed_t plateau_speed);

/**
 * Homes the specified axes. Homing an axis means moving it in the negative
 * direction until it reaches its min endstop.
 *
 * @param x boolean indicating whether or not to home the x axis
 * @param y boolean indicating whether or not to home the y axis
 * @param z boolean indicating whether or not to home the z axis
 */
void plan_home_axes(bool x, bool y, bool z);

#endif //PLANNER_H
